package deroulementjeu;


import java.awt.Color;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

import affichage.JeuView;

import regles.Regle;
import terrain.Terrain;
import unite.Pokemon;
import unite.Unite;


public class Partie implements Serializable {
    private static final long serialVersionUID = 1L;

    /** Nombres de tours */
    private int nbTours;
	
    /** Règle du jeu à utiliser */
    private Regle regle;
	
    /** Terrain de la partie */
    private Terrain terrain;
	
    /** Ensemble des équipes du jeu */
    private ArrayList<Equipe> equipes;
	
    /** L'équipe qui est en train de jouer son tour */
    private Equipe equipeEnCours;
	
    /** La JFrame jeuView qui est utilisée lors de la fin de partie */
    private JeuView jeuView;
	
    /**
     * Constructeur de la classe partie
     * @param r règle du jeu à utiliser au cours de la partie
     */
    public Partie(Regle r, Terrain t) {
		
        setNbTours(0);
        this.regle = r;
        this.terrain = t;
        equipes = new ArrayList<Equipe>();
        equipes.ensureCapacity(3);
		
        equipes.add(0, new Equipe(this, "Team1", Color.red, TypeEquipe.HUMAIN));
        equipes.add(1, new Equipe(this, "Team2", Color.cyan, TypeEquipe.HUMAIN));
        equipes.add(2, new Equipe(this, "Team3", Color.black, TypeEquipe.OBJET));
	
    }
	
    public TypeEquipe getTypeJoueur(int index) {
        return equipes.get(index).getType();
    }
	
    public void setTypeJoueur(int index, TypeEquipe te) {
        equipes.get(index).setType(te);
    }
	
    /**
     * Ajout d'une équipe à la partie
     * @param e l'équipe à ajouter
     */
    public void ajouterEquipe(Equipe e) {
        equipes.add(e);
        e.setPartie(this);
    }
	
    /**
     * Accesseur au terrain de la partie
     * @return le terrain de la partie
     */
    public Terrain getTerrain() {
        return terrain;
    }
	
    /**
     * Accesseur à la JFrame du jeu
     * @return la fenêtre JeuView
     */
    public JeuView getJeuView() {
        return this.jeuView;
    }
	
    /**
     * Setter de la JFrame du jeu
     * @param la fenêtre JeuView
     */
    public void setJeuView(JeuView jv) {
        this.jeuView = jv;
    }
	
    /**
     * Accesseur à la règle du jeu de la partie
     * @return la règle du jeu de la partie
     */
    public Regle getRegle() {
        return regle;
    }
	
    /**
     * Simule un tour de jeu : fais jouer l'ensemble des équipes de la partie
     */
    public void tourDeJeu() {}

    public void setNbTours(int nbTours) {
        this.nbTours = nbTours;
    }

    public int getNbTours() {
        return nbTours;
    }
	
    /**
     * Méthode d'initialisation d'une partie
     */
    public void init() {
        Iterator<Equipe> i = equipes.iterator();
		
        while (i.hasNext()) {
            i.next().init();
        }
		
        // Fixer les ennemis de chaque équipe 
        equipes.get(0).setEnnemi(equipes.get(1));
        equipes.get(1).setEnnemi(equipes.get(0));
		
        equipes.get(0).setNbPotions(this.getRegle().getNbPotion());
        equipes.get(1).setNbPotions(this.getRegle().getNbPotion());
		
        equipeEnCours = equipes.get((int) Math.random() * 2);
    }
	
    /**
     * Méthode la sauvegarde d'une partie dans un fichier, par serialization.
     * @param fichier Fichier dans lequel il faut enregistrer la partie.
     */
    public void sauvegarde(String fichier) {
        try {
            FileOutputStream fos = new FileOutputStream(fichier);
            ObjectOutputStream oos = new ObjectOutputStream(fos);

            try {
                oos.writeObject(this); 
                oos.flush();
            } finally {
                try {
                    oos.close();
                } finally {
                    fos.close();
                }
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
	
    /**
     * Fonction permettant de déserializer une partie.
     * @param fichier Fichier qui contient la partie à charger.
     * @return La partie qui était stockée dans le fichier.
     */
    public Partie charger(String fichier) {
        Partie p = null;

        try {
            FileInputStream fis = new FileInputStream(fichier);
            ObjectInputStream ois = new ObjectInputStream(fis);

            try {	
                p = (Partie) ois.readObject(); 
            } finally {
                try {
                    ois.close();
                } finally {
                    fis.close();
                }
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }

        return p;
    }
	
    /**
     * Renvoie l'équipe qui se situe à l'index index de l'ArrayList equipe
     * @param index du tableau
     * @return l'équipe
     */
    public Equipe getEquipe(int index) {
        return this.equipes.get(index);
    }
	
    public Equipe getEquipeEnCours() {
        return this.equipeEnCours;
    }
	
    public void setEquipeEnCours(Equipe e) {
        this.equipeEnCours = e;
    }

    /**
     * Vérifie si la fin de partie a été atteinte :
     * si l'une des parties qui jouent effectivement n'a plus de dresseur ou plus aucun pokémon
     * @return true si la fin de la partie est atteinte
     */
    public Equipe finDePartie() {
        // Plus de dresseur
        if (equipes.get(0).getDresseur() == null) {
            return equipes.get(0);
        }
        if (equipes.get(1).getDresseur() == null) {
            return equipes.get(1);
        }
        // Plus de pokémons
        Pokemon pok = null;

        for (Unite u : equipes.get(0).getUnites()) {
            if (u.estPokemon()) {
                pok = (Pokemon) u;
                break;
            }
        }
        if (pok == null) {
            return equipes.get(0);
        }
		
        pok = null;
        for (Unite u : equipes.get(1).getUnites()) {
            if (u.estPokemon()) {
                pok = (Pokemon) u;
                break;
            }
        }
        if (pok == null) {
            return equipes.get(1);
        }
		
        return null;
    }
	
    public void initTour() {
        Iterator<Equipe> i = equipes.iterator();
		
        while (i.hasNext()) {
            i.next().initTour();
        }
    }	
}
